import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Scanner;

// 文件相关操作
public class FileOperation {

    /**
     * 从指定的文件中读取内容，并将所有单词添加到给定的单词列表中。
     *
     * @param filename 要读取的文件名。
     * @param words 用于存储从文件中读取的单词的列表。
     * @return 如果成功读取文件并添加单词，则返回true；否则返回false。
     */
    // 读取文件名称为filename中的内容，并将其中包含的所有词语放进words中
    public static boolean readFile(String filename, ArrayList<String> words){
        // 检查文件名和单词列表是否为空，如果是，则返回false。
        if (filename == null || words == null){
            System.out.println("filename is null or words is null");
            return false;
        }

        // 初始化扫描器以读取文件。
        // 文件读取
        Scanner scanner;
        try {
            // 创建文件对象并检查文件是否存在。
            File file = new File(filename);
            if(file.exists()){
                // 使用UTF-8编码打开文件，并通过BufferedInputStream提高读取速度。
                FileInputStream fis = new FileInputStream(file);
                scanner = new Scanner(new BufferedInputStream(fis), "UTF-8");
                // 使用英文地区设置，以确保单词分隔的一致性。
                scanner.useLocale(Locale.ENGLISH);
            }
            else {
                System.out.println("文件不存在！");
                return false;
            }
        }
        catch(IOException ioe){
            // 如果打开文件失败，打印错误消息并返回false。
            System.out.println("Cannot open " + filename);
            return false;
        }

        // 如果扫描器中有下一行，说明文件不为空。
        // 简单分词
        // 这个分词方式相对简陋, 没有考虑很多文本处理中的特殊问题
        // 在这里只做demo展示用
        if (scanner.hasNextLine()) {
            // 以整个文件内容为单位进行分割。
            String contents = scanner.useDelimiter("\\A").next();
            // 从文件内容中提取单词。
            int start = firstCharacterIndex(contents, 0);
            for (int i = start + 1; i <= contents.length(); )
                if (i == contents.length() || !Character.isLetter(contents.charAt(i))) {
                    // 将提取到的单词转换为小写，并添加到单词列表中。
                    String word = contents.substring(start, i).toLowerCase();
                    words.add(word);
                    // 寻找下一个单词的起始位置。
                    start = firstCharacterIndex(contents, i);
                    i = start + 1;
                } else
                    i++;
        }

        // 成功读取文件并添加单词，返回true。
        return true;
    }


    /**
     * 从给定的字符串的指定位置开始，查找第一个字母字符的索引。
     * 如果从指定位置开始到字符串末尾没有字母字符，则返回字符串的长度。
     *
     * @param s 输入的字符串
     * @param start 开始查找的索引位置
     * @return 第一个字母字符的索引，或字符串长度 if 不存在字母字符
     */
    // 寻找字符串s中，从start的位置开始的第一个字母字符的位置
    private static int firstCharacterIndex(String s, int start){
        // 从指定的start位置开始遍历字符串
        for( int i = start ; i < s.length() ; i ++ )
            // 如果当前字符是字母字符，则返回当前索引
            if( Character.isLetter(s.charAt(i)) )
                return i;
        // 如果遍历完字符串后仍未找到字母字符，则返回字符串长度
        return s.length();
    }

}
